package com.gitee.ice1938.adcode.fun;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class DictAdministrativeAreaServiceImpl implements DictAdministrativeAreaService, CommandLineRunner {

	/**
	 * Logger for this class
	 */
	private static final Logger logger = LoggerFactory.getLogger(DictAdministrativeAreaServiceImpl.class);
//	@Autowired
//	private CacheManager cacheManager;

	@Autowired
	private DictAdministrativeAreaRepository dictAdministrativeAreaRepository;

	@Override
	public Page<DictAdCodeModel> queryPage(Map<String, Object> params, Pageable pagebale, Order order) {
		Page<DictAdCodeModel> data = dictAdministrativeAreaRepository.queryPage(params, pagebale, order);

		return data;
	}

	/**
	 * 使用批量插入必须显示声明事物，否则会按照默认事物，每条数据一个事物处理
	 * 
	 * @throws IOException
	 */
	@Override
	@Transactional//(propagation = Propagation.REQUIRES_NEW)
	public int importData(List<DataRecord> records, int year, boolean isallCode, String userPrincipal)
			throws IOException {
		logger.info("importData year :{} start", year);
		int last = dictAdministrativeAreaRepository.getLastYear();
		if (last >= year) {// 不重复导入数据
			logger.info("importData year :{} return ", last);
			return last;
		}
		Calendar cl = Calendar.getInstance();
		cl.set(Calendar.YEAR, year);
		cl.set(Calendar.MONTH, Calendar.JANUARY);
		cl.set(Calendar.DAY_OF_MONTH, 1);
		List<DictAdCodeModel> addData = new ArrayList<>();
		List<DictAdCodeModel> revokeData = new ArrayList<>();
		if (isallCode) {
			// 查询数据库中所有有效数据
			List<DictAdCodeModel> dataDb = dictAdministrativeAreaRepository.findAll();
			Map<String, List<DictAdCodeModel>> mapDataDb = new HashMap<>();
			dataDb.forEach(itemdb -> {
				List<DictAdCodeModel> sublist = mapDataDb.get(itemdb.getAdCode());
				if (sublist == null) {
					sublist = new ArrayList<>();
					mapDataDb.put(itemdb.getAdCode(), sublist);
				}
				sublist.add(itemdb);
			});

			//
			Map<String, DictAdCodeModel> mapDataImport = new HashMap<>();
			List<DictAdCodeModel> addDuplicateData = new ArrayList<>();
			if (year == 1980) {
				cl.set(Calendar.MONTH, Calendar.DECEMBER);
				cl.set(Calendar.DAY_OF_MONTH, 01);
			}
			for (DataRecord record : records) {
				DictAdCodeModel item = new DictAdCodeModel();
				item.setAdCode(record.getAdCode());
				item.setAdName(record.getAdName());
				item.setStartTime(cl.getTime());
				if (record.getAddflag()) {
					mapDataImport.put(item.getAdCode(), item);
				} else {
					Date d = record.getRevokeTime() == null ? cl.getTime() : record.getRevokeTime();
					item.setRevokeTime(d);
					revokeData.add(item);
				}
			}
			/// 添加新的,交集不用动,标识注销的
			for (DictAdCodeModel item : mapDataImport.values()) {
				// 单纯添加---数据库中有效数据不存在,即为新增数据
				if (!mapDataDb.containsKey(item.getAdCode())) {
					addData.add(item);
					logger.info("addData year:{} item :{} ", year, item);
				}
			}
			dictAdministrativeAreaRepository.batchInsert(addData, userPrincipal);
			//
			for (Entry<String, List<DictAdCodeModel>> i : mapDataDb.entrySet()) {
				String key = i.getKey();
				List<DictAdCodeModel> value = i.getValue();
				// 单纯撤销--- 数据库中有数据存在,但不在导入数据中的数据,标记为删除,设置撤销时间
				if (!mapDataImport.containsKey(key)) {
					value.forEach(dbitem -> {
						if (dbitem.getRevokeTime() == null) {
							dbitem.setRevokeTime(cl.getTime());
							revokeData.add(dbitem);
							logger.info("revokeData year:{} dbitem:{}", year, dbitem);
						}
					});
				} else {
					// 数据库中有数据存在,导入数据中也存在的数据,但名称有变化的数据,标记为删除,设置撤销时间
					DictAdCodeModel item = mapDataImport.get(key);
					value.forEach(dbitem -> {
						if (!dbitem.equals(item)) {
							if (dbitem.getRevokeTime() == null) {
								dbitem.setRevokeTime(cl.getTime());
								revokeData.add(dbitem);// DB数据标记撤销
								item.setUseCount(dbitem.getUseCount() + 1);
								addDuplicateData.add(item);// 新增数据准备
							}
							logger.info("revokeData year:{} item :{} dbitem:{}", year, item, dbitem);
						}
					});
				}
			}
			dictAdministrativeAreaRepository.batchRevoke(revokeData, userPrincipal);
			dictAdministrativeAreaRepository.batchInsert(addDuplicateData, userPrincipal);
		} else {
			for (DataRecord record : records) {
				DictAdCodeModel item = new DictAdCodeModel();
				item.setAdCode(record.getAdCode());
				item.setAdName(record.getAdName());
				item.setStartTime(cl.getTime());
				Date d = record.getRevokeTime() == null ? cl.getTime() : record.getRevokeTime();
				if (record.getAddflag()) {
					addData.add(item);
				} else {
					item.setRevokeTime(d);
					revokeData.add(item);
				}
			}
			dictAdministrativeAreaRepository.batchInsert(addData, userPrincipal);
			dictAdministrativeAreaRepository.batchRevoke(revokeData, userPrincipal);
		}

		dictAdministrativeAreaRepository.updateCodeModifiedTime(year);
		logger.info("importData year :{} end", year);
		return year;
	}

	@Override
//	@Cacheable(value = AdminDictAdministrativeConfig.cach_cityselect)
	public Map<String, Object> queryForCityselect(int year) {

		Map<String, Object> data = new HashMap<String, Object>();
		List<Map<String, Object>> citylist = new ArrayList<>();
		data.put("citylist", citylist);
		// 获得省级数据
		List<DictAdCodeModel> dataP = dictAdministrativeAreaRepository.queryForCityByYear("__0000", year);
		for (DictAdCodeModel p : dataP) {
			String pcode = p.getAdCode().toString().substring(0, 2);
			Map<String, Object> pMap = new HashMap<String, Object>();
			List<Map<String, Object>> cList = new ArrayList<>();
			pMap.put("p", p.getAdName());
			// pMap.put("code", p.get("areaOne"));
			citylist.add(pMap);
			// 获得市地级数据
			List<DictAdCodeModel> datan = dictAdministrativeAreaRepository.queryForCityByYear(pcode + "__00", year);
			if (datan.size() == 1) {
				datan = dictAdministrativeAreaRepository.queryForCityByYear(pcode + "____", year);
				// 不存在县级代码，直接管理县级区域
				for (DictAdCodeModel n : datan) {
					String ncode_ = n.getAdCode().toString().substring(2, 6);
					if (ncode_.equals("0000")) {
						// 排除省级数据
						continue;
					}
					// 地级码段
					Map<String, Object> nMap = new HashMap<String, Object>();
					nMap.put("n", n.getAdName());
					// nMap.put("code", n.get("areaOne"));
					cList.add(nMap);
				}

			} else {
				for (DictAdCodeModel n : datan) {
					String ncode_ = n.getAdCode().toString().substring(2, 6);
					if (ncode_.equals("0000")) {
						// 排除省级数据
						continue;
					}
					// 地级码段
					String ncode = n.getAdCode().toString().substring(2, 4);
					Map<String, Object> nMap = new HashMap<String, Object>();
					nMap.put("n", n.getAdName());
					// nMap.put("code", n.get("areaOne"));
					cList.add(nMap);
					// 说明市级存在县级码段
					List<DictAdCodeModel> dataa = dictAdministrativeAreaRepository
							.queryForCityByYear(pcode + ncode + "__", year);
					if (datan != null && !datan.isEmpty()) {
						List<Map<String, Object>> nList = new ArrayList<>();
						for (DictAdCodeModel a : dataa) {
							String acode = a.getAdCode().toString().substring(4, 6);
							if (acode.equals("00")) {
								continue;
							}
							Map<String, Object> sMap = new HashMap<String, Object>();
							sMap.put("s", a.getAdName());
							// sMap.put("code", a.get("areaOne"));
							nList.add(sMap);
						}
						nMap.put("a", nList);
					}
				}

			}
			pMap.put("c", cList);
		}

		return data;
	}

	@Override
	public void run(String... args) throws Exception {
//		if (cacheManager instanceof MissingJCacheCacheManager) {
//			MissingJCacheCacheManager cacheManager_ = (MissingJCacheCacheManager) cacheManager;
//			javax.cache.configuration.Configuration configuration = new MutableConfiguration<>().setStoreByValue(false)
//					.setStatisticsEnabled(true);
//			cacheManager_.regCacheConfig(AdminDictAdministrativeConfig.cach_cityselect, configuration);
//		}

	}
}
